using QntPlatform.Strategy.S2;
using System;
using System.Linq;

namespace QntPlatform.Strategy.CmdCtrl
{

    /// <summary>
    /// 小于4小时直接按止盈1卖出，大于则卖出一半，后面的跟踪
    /// </summary>
    public class StepProfitRun: CmdHandlePart
    {
       readonly decimal amSum;
        decimal nowAmount;
        StrategyBase2 strategyBase2;
        decimal profitSlideDownRate = 0.85m;
       public decimal StopProfitForSlideRate { get; set; }=0.01m;
        public int Period { get; }

        /* 设想
一个列表都是函数，每个函数可以获得一个任务处理接口，每次变化获取调用接口，一个接口完毕，调用下一个函数获取接口
*/



        public StepProfitRun(IStrategy  parent,TvCmdHandler.AutoSellOrder autoSellOrder,int period) : base(parent)
        {
            AutoSellOrder= autoSellOrder;
            Period = period;
            amSum = autoSellOrder.Amount;
            nowAmount = amSum;
            strategyBase2 = parent as StrategyBase2;
        }
        decimal[] amountArr = null;
        public override void Init()
        {
            if (Period < 4 * 3600)
            {
                amountArr = new decimal[] { AutoSellOrder.Amount, 0 };
            }
            else
            {
                var amount = greedyRoundSplit(AutoSellOrder.Amount, AutoSellOrder.Amount / 2);
                var rea = AutoSellOrder.Amount - amount;
                amountArr = new decimal[] { amount, rea };
            }
           
            Exchange.TickerChangeEvent += Exchange_TickerChangeEvent;
        }
        private void Exchange_TickerChangeEvent(object sender, Ticker e)
        {
            if (strategyBase2 != null && strategyBase2.IsEnd)
            {
                OnExit();
            }
            TickerChangeListening(e);
        }

        TvCmdHandler.AutoSellOrder AutoSellOrder;
       
        public override void OnExit(Exception ex = null)
        {
            Exchange.TickerChangeEvent -= Exchange_TickerChangeEvent;
            //Parent.OnExit();
        }

        public decimal greedyRoundSplit(decimal source,decimal form) {
          var fp=  Exchange.getAmount(form);
           return fp == 0 ? source : fp;
        }
        TrailingProfit lastTP;

      public  void TickerChangeListening(Ticker tck)
        {
            var item = AutoSellOrder;
            //检查止损
            if (nowAmount>0&&ISysFun.calcUnitProfit(tck.Buy, item.StopLossPrice, AutoSellOrder.Direction == SideDirection.CloseBuy) <= 0)
            {
                log.Debug("止损交易:", new { item, tck });
               // execTrade(item.Direction, item.Amount,item);
                Exchange.CreateOrder(nowAmount, item.Direction,info:new Db.LogInfo (){ ParentActId=item.SourceOrderId+"",Info2="止损,市价:"+tck.Buy });
                OnExit();
                return;
            }
            //检查止盈，跟踪止盈
            if (item.ProfitStep==1)
            {
                if (lastTP==null)
                {
                    log.Error("lastTP为null");
                    return;
                    //OnExit(new ArgumentException("lastTP为null"));
                }
                if (lastTP.Check(tck.Last))
                {
                    //execTrade(item.Direction, lastTP.Amount, new { lastTP,tck.Last});
                    Exchange.CreateOrder(lastTP.Amount, item.Direction, info: new Db.LogInfo() { ParentActId = item.SourceOrderId + "", Info2 = "止盈,市价:"+tck.Last });
                    OnExit();
                }
                return;
            }
          
            var upf= ISysFun.calcUnitProfit(tck.Buy,item.ProfitPrices[item.ProfitStep],item.Direction==SideDirection.CloseBuy);
           
             if (upf<0)
                return;

         if (item.ProfitStep == 0)
            {
                //var amount = item.Amount / 2;
                IConvertible id = 0;
                var amount1 = amountArr[0];
                if (amount1 > 0)
                  //  id = execTrade(item.Direction, amount1, new { nowBuy = tck.Buy });
               id= Exchange.CreateOrder(amount1, item.Direction, info: new Db.LogInfo() { ParentActId = item.SourceOrderId + "", Info2 = "止盈1/3,市价:" + tck.Buy }).Result;
                item.ProcInfo.Add($"止盈0成交,剩余仓位:{item.Amount},成交id:{id}");
                item.ProfitStep++;
                item.Amount = amountArr[1];
                nowAmount = 0;
                if (item.Amount == 0)
                {
                    log.Debug("止盈成交,剩余仓位0，结束", $"{item.SourceOrderId},{item.Amount},{item.ProcInfo.Aggregate((p1, p2) => p1 + "," + p2)}");
                    OnExit();
                    return;
                }
                log.Debug("止盈成交,准备跟踪止盈", $"{item.SourceOrderId},{item.Amount},{item.ProcInfo.Aggregate((p1, p2) => p1 + "," + p2)}");
                lastTP = new TrailingProfit()
                {
                    InitPrice = tck.Buy,
                    IsLong = item.Direction == SideDirection.CloseBuy,
                    Amount = item.Amount,
                    profitSlideRate=StopProfitForSlideRate
                };
                return;
            } 
            else
            {
                throw new QntException("无法处理的步骤", item);
            }
        }
       
        /// <summary>
        /// 追踪止盈信息数据
        /// </summary>
    class TrailingProfit
    {
            /// <summary>
            /// 最高盈利率
            /// </summary>
            public decimal topProfitRate { get; private set; } 
            /// <summary>
            /// 初始价格
            /// </summary>
           public decimal InitPrice { get; set; }
            /// 止盈回撤率
            public decimal profitSlideRate { get; set; }= 0.001m;
            /// 止盈率
            //public decimal profitRate { get; set; }
            public  bool IsLong { get; set; }
            public decimal Amount { get; set; }
           public bool Check(decimal nowPrice) {
                var nowRate = ISysFun.CalcProfitRate(nowPrice, InitPrice,IsLong);
                if (nowRate > topProfitRate)
                {
                    topProfitRate = nowRate;
                    return false;
                }
                if ((topProfitRate - nowRate) >= topProfitRate * profitSlideRate)
                {
                    return true;
                }
                return false;
            }
        }
    }



}
